package com.example.guesswho.util

import android.content.Context
import android.graphics.Bitmap
import android.net.Uri
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow

/**
 * UtilityManager - Central coordinator for audio and image utilities
 * Provides simplified API for common game utility functions
 */
class UtilityManager private constructor(private val context: Context) {
    
    private val audioPlayer = AudioPlayer.getInstance(context)
    private val cartoonFilter = CartoonFilter.getInstance(context)
    
    // State management
    private val _isProcessingImage = MutableStateFlow(false)
    val isProcessingImage: StateFlow<Boolean> = _isProcessingImage
    
    private val _currentFilterStyle = MutableStateFlow(CartoonFilter.FilterStyle.CLASSIC_CARTOON)
    val currentFilterStyle: StateFlow<CartoonFilter.FilterStyle> = _currentFilterStyle
    
    companion object {
        @Volatile
        private var instance: UtilityManager? = null
        
        fun getInstance(context: Context): UtilityManager {
            return instance ?: synchronized(this) {
                instance ?: UtilityManager(context.applicationContext).also { instance = it }
            }
        }
    }
    
    //region Audio Functions
    
    /**
     * Play success sound with haptic feedback
     */
    fun playSuccessSound() {
        audioPlayer.playSuccessSound()
    }
    
    /**
     * Play failure sound
     */
    fun playFailureSound() {
        audioPlayer.playFailureSound()
    }
    
    /**
     * Play celebration sound for special achievements
     */
    fun playCelebrationSound() {
        audioPlayer.playCelebrationSound()
    }
    
    /**
     * Play random easter egg sound
     */
    fun playRandomEasterEgg() {
        audioPlayer.playRandomEasterEgg()
    }
    
    /**
     * Play custom sound from resources
     */
    fun playCustomSound(soundResId: Int) {
        audioPlayer.playSound(soundResId)
    }
    
    /**
     * Set audio volume (0.0f to 1.0f)
     */
    fun setAudioVolume(volume: Float) {
        audioPlayer.setVolume(volume.coerceIn(0f, 1f))
    }
    
    //region Cartoon Filter Functions
    
    /**
     * Apply cartoon filter to bitmap with current style
     */
    fun applyCartoonFilter(
        bitmap: Bitmap,
        callback: (Result<Bitmap>) -> Unit
    ) {
        _isProcessingImage.value = true
        cartoonFilter.applyCartoonFilter(bitmap, _currentFilterStyle.value) { result ->
            _isProcessingImage.value = false
            callback(result)
        }
    }
    
    /**
     * Apply cartoon filter to image URI with current style
     */
    fun applyCartoonFilter(
        imageUri: Uri,
        callback: (Result<Bitmap>) -> Unit
    ) {
        _isProcessingImage.value = true
        cartoonFilter.applyCartoonFilter(imageUri, _currentFilterStyle.value) { result ->
            _isProcessingImage.value = false
            callback(result)
        }
    }
    
    /**
     * Apply cartoon filter and upload to Parse
     */
    fun applyAndUploadCartoonFilter(
        bitmap: Bitmap,
        fileName: String? = null,
        callback: (Result<String>) -> Unit
    ) {
        _isProcessingImage.value = true
        cartoonFilter.applyAndUploadCartoonFilter(bitmap, _currentFilterStyle.value, fileName) { result ->
            _isProcessingImage.value = false
            callback(result)
        }
    }
    
    /**
     * Set cartoon filter style
     */
    fun setFilterStyle(style: CartoonFilter.FilterStyle) {
        _currentFilterStyle.value = style
    }
    
    /**
     * Get available cartoon filter styles
     */
    fun getAvailableFilterStyles(): List<CartoonFilter.FilterStyleInfo> {
        return cartoonFilter.getAvailableStyles()
    }
    
    //region Game-Specific Utility Functions
    
    /**
     * Handle game event with appropriate audio feedback
     */
    fun handleGameEvent(event: GameEvent) {
        when (event) {
            GameEvent.ANSWER_CORRECT -> {
                playSuccessSound()
                // Occasionally play celebration sound for streaks
                if (Math.random() < 0.1) { // 10% chance
                    playCelebrationSound()
                }
            }
            GameEvent.ANSWER_WRONG -> {
                playFailureSound()
            }
            GameEvent.GAME_WIN -> {
                playCelebrationSound()
                // Play easter egg sound occasionally
                if (Math.random() < 0.3) { // 30% chance
                    playRandomEasterEgg()
                }
            }
            GameEvent.GAME_LOSE -> {
                playFailureSound()
            }
            GameEvent.ROOM_JOIN -> {
                playCustomSound(getRawResourceId("room_join_sound") ?: return)
            }
            GameEvent.ACHIEVEMENT_UNLOCK -> {
                playCelebrationSound()
                playRandomEasterEgg()
            }
        }
    }
    
    /**
     * Create and upload cartoon profile picture for user
     */
    fun createAndUploadCartoonProfile(
        originalBitmap: Bitmap,
        username: String,
        callback: (Result<String>) -> Unit
    ) {
        _isProcessingImage.value = true
        
        // Use anime style for profile pictures
        _currentFilterStyle.value = CartoonFilter.FilterStyle.ANIME_STYLE
        
        applyAndUploadCartoonFilter(
            originalBitmap,
            "profile_${username}_${System.currentTimeMillis()}.jpg",
            callback
        )
    }
    
    /**
     * Create cartoon avatar from user photo and play success sound
     */
    fun createCartoonAvatarWithFeedback(
        bitmap: Bitmap,
        callback: (Result<String>) -> Unit
    ) {
        applyAndUploadCartoonFilter(bitmap, "avatar_${System.currentTimeMillis()}.jpg") { result ->
            when {
                result.isSuccess -> {
                    playSuccessSound()
                    playRandomEasterEgg()
                }
                result.isFailure -> {
                    playFailureSound()
                }
            }
            callback(result)
        }
    }
    
    //region Helper Functions
    
    private fun getRawResourceId(resourceName: String): Int? {
        return try {
            val resId = context.resources.getIdentifier(
                resourceName,
                "raw",
                context.packageName
            )
            if (resId != 0) resId else null
        } catch (e: Exception) {
            null
        }
    }
    
    /**
     * Clean up all utility resources
     */
    fun cleanup() {
        audioPlayer.release()
        cartoonFilter.release()
        instance = null
    }
    
    /**
     * Game events enum
     */
    enum class GameEvent {
        ANSWER_CORRECT,
        ANSWER_WRONG,
        GAME_WIN,
        GAME_LOSE,
        ROOM_JOIN,
        ACHIEVEMENT_UNLOCK
    }
}

/**
 * Extension functions for simplified utility usage
 */

// Audio extensions
fun Context.playSuccessSound() {
    UtilityManager.getInstance(this).playSuccessSound()
}

fun Context.playFailureSound() {
    UtilityManager.getInstance(this).playFailureSound()
}

fun Context.playCelebrationSound() {
    UtilityManager.getInstance(this).playCelebrationSound()
}

// Cartoon filter extensions
suspend fun Bitmap.applyCartoonFilter(
    context: Context,
    style: CartoonFilter.FilterStyle = CartoonFilter.FilterStyle.CLASSIC_CARTOON
): Result<Bitmap> {
    return UtilityManager.getInstance(context).run {
        suspendCancellableCoroutine { continuation ->
            applyCartoonFilter(this@applyCartoonFilter) { result ->
                continuation.resume(result)
            }
        }
    }
}

suspend fun Bitmap.applyAndUploadCartoonFilter(
    context: Context,
    fileName: String? = null
): Result<String> {
    return UtilityManager.getInstance(context).run {
        suspendCancellableCoroutine { continuation ->
            applyAndUploadCartoonFilter(this@applyAndUploadCartoonFilter, fileName) { result ->
                continuation.resume(result)
            }
        }
    }
}

// Game event handling extension
fun Context.handleGameEvent(event: UtilityManager.GameEvent) {
    UtilityManager.getInstance(this).handleGameEvent(event)
}